#ifndef THREADSESSAOTEST_H
#define THREADSESSAOTEST_H

#include "../../Trabalho3/Trabalho3_Servidor/includes/controller/Operacoes.h"
#include "../../Trabalho3/Trabalho3_Servidor/includes/model/ModoAbertura.h"

#include <QString>
#include <QObject>
#include <QDebug>
#include <QThread>
#include <QHostAddress>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QDataStream>
#include <QByteArray>
#include <QFile>
#include <QList>

namespace controller
{

	enum TesteCases
	{
		pingCliente,
		adicionarClienteNaoExistente,
		adicionarClienteExistente,
		loginClienteNaoExistente,
		loginClienteJaLogado,
		loginClienteExistente,
		logoutClienteNaoLogado,
		logoutClienteLogado,
		adicionarArquivoExistente,
		adicionarArquivoNaoExistente,
		AdicionarArquivosExistentes,
		AdicionarArquivoNaoExistente,
		AdicionarArquivoDuplicado,
		getArquivoNaoExistente,
		getArquivoBloqueado, // Esse teste precisa rodar junto com o getArquivoBloqueiaEspera
		getArquivoBloquearSendoUsado, // Esse teste precisa rodar junto com getArquivoExistenteEspera
		getArquivoBloqueiaEspera,
		getArquivoExistente,
		getArquivoExistenteEspera,
		apagarArquivoNaoAberto,
		apagarArquivoNaoExistente,
		// Esse teste precisa rodar junto com o getArquivoBloqueiaEspera ou getArquivoExistenteEspera
		apagarArquivoBloqueado,
		apagarArquivoAberto,
		fecharArquivoNaoAberto,
		fecharArquivoNaoExistente,
		// Esse teste precisa rodar junto com o getArquivoBloqueiaEspera ou getArquivoExistenteEspera
		fecharArquivoAbertoSendoUsado,
		fecharArquivoAbertoBloqueado
	};

	class ThreadSessaoTest : public QThread
	{
		Q_OBJECT
		public:
			ThreadSessaoTest( const QString &ip, const unsigned short &porta,
				ThreadSessaoTest *sibling, TesteCases teste, QObject *parent = 0 );
			virtual ~ThreadSessaoTest();

			void podeContinuar( bool podeContinuarTeste ) { this->podeContinuarTeste = podeContinuarTeste; }
			void setSibling( ThreadSessaoTest *sibling ) { this->sibling = sibling; }
		protected:
			void run();
		private:
			QByteArray array;
			QDataStream *stream;
			QHostAddress address;
			QTcpSocket *socket;
			unsigned short porta;

			QString* getError( const char* );

			void pingTeste(); // OK
			void adicionarClienteTeste( const QString& ); // OK
			void loginTeste( const QString& ); // OK
			void logoutTeste(); // OK
			void adicionarArquivoTeste( const QString &fileName ); // OK
			void adicionarArquivosPorExtTeste( const QList<QFile*>& ); // Nao implementado ainda
			void getArquivoTeste( const QString&, model::ModoAbertura ); // OK
			void apagarArquivoTeste( const QString& ); // OK
			void fecharArquivoTeste( const QString& ); // OK
			//void renomearArquivoTeste();
			//void getDadosArquivoTeste();

			void adicionarClienteTesteFail(); // OK
			void adicionarClienteTesteSuccess(); // OK
			void loginTesteFail( TesteCases ); // OK
			void loginTesteSuccess(); // OK
			void logoutTesteFail(); // OK
			void logoutTesteSuccess(); // OK
			void adicionarArquivoTesteFail(); // OK
			void adicionarArquivoTesteSuccess(); // OK
			void adicionarArquivosTesteFail(); // Nao implementado
			void adicionarArquivosTesteSuccess(); // Nao implementado
			void getArquivoTesteFail( TesteCases ); // OK
			void getArquivoTesteSuccess( TesteCases ); // OK
			void apagarArquivoTesteFail( TesteCases ); // OK
			void apagarArquivoTesteSuccess(); // OK
			void fecharArquivoTesteFail( TesteCases ); // OK
			void fecharArquivoTesteSuccess( TesteCases ); // OK

			void waitRead( bool firstWait = true );
			void waitWrite();

			// Indica qual teste vai ser executado
			TesteCases teste;
			// Essa thread e a thread concorrente, logo e preciso esperar ela terminar para terminar..
			ThreadSessaoTest *sibling;
			volatile bool podeContinuarTeste;
		signals:
			void temArquivo();
	};
}

#endif
